/*
 * Copyright 2008 Mark Davidson.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.doofer

import com.documentum.fc.common.*

/**
 * Contains convenience methods for reading and writing attribute values.
 *
 * @author Mark Davidson
 */
class AttribUtil {

    /**
     * Constructor
     */
    AttribUtil() {}


    /**
     * Reads multiple attribute values from an IDfTypedObject (e.g. IDfPersistentObject,
     * IDfCollection, etc). If attribute names are not specified then all attribute values
     * are returned. The named parameters are:
     *
     * <ul>
     * <li>object - the typed object</li>
     * <li>attribNames - list of attribute names (optional)</li>
     * </ul>
     *
     * @param params The named parameters. See description for more info.
     * @return The attribute value
     * @throws DfException
     */
    def readAttribs(Map params) {

        def object = params.object
        def attribNames = params.attribNames
        def attribValues = [:]

        // build list of attrib names if reqd
        if(!attribNames) {
            attribNames = []
            def numAttribs = object.attrCount
            for(i in 0..<numAttribs) {
                attribNames << object.getAttr(i).name
            }
        }

        // build map of attrib key/value pairs
        for(attribName in attribNames) {
            attribValues."$attribName" = readAttrib(object: object, attribName: attribName)
        }

        attribValues
    }

    /**
     * Reads an attribute value from an IDfTypedObject (e.g. IDfPersistentObject,
     * IDfCollection, etc). The named parameters are:
     *
     * <ul>
     * <li>object - the typed object</li>
     * <li>attribName - the attribute name</li>
     * <li>attribType - the attribute type (optional)</li>
     * <li>repeating - whether the attribute is a repeating value (optional)</li>
     * </ul>
     *
     * @param params The named parameters. See description for more info.
     * @return The attribute value
     * @throws DfException
     */
    def readAttrib(Map params) {

        def object = params.object
        def attribName = params.attribName
        def attribType = params?.attribType
        def repeating = params?.repeating
        def attribValue = null

        def numValues = object.getValueCount(attribName)

        if(!attribType) {
            attribType = object.getAttrDataType(attribName)
        }

        if(repeating == null) {
            repeating = object.isAttrRepeating(attribName)
        }

        if(!repeating) {
        	// single attribute
        	switch(attribType) {
        		case IDfAttr.DM_BOOLEAN:
                    attribValue = object.getBoolean(attribName)
                    break
                case IDfAttr.DM_DOUBLE:
                    attribValue = object.getDouble(attribName)
                    break
                case IDfAttr.DM_ID:
                    attribValue = object.getId(attribName).id
                    break
                case IDfAttr.DM_INTEGER:
                    attribValue = object.getInt(attribName)
                    break
                case IDfAttr.DM_STRING:
                    attribValue = object.getString(attribName)
                    break
                case IDfAttr.DM_TIME:
                    attribValue = object.getTime(attribName).date
                    break
        	}
        } else {
        	// repeating attribute
            attribValue = []

            for(j in 0..<numValues) {
	            switch(attribType) {
	            	case IDfAttr.DM_BOOLEAN:
	                    attribValue << object.getRepeatingBoolean(attribName, j)
	                    break
                    case IDfAttr.DM_DOUBLE:
                        attribValue << object.getRepeatingDouble(attribName, j)
                        break
                    case IDfAttr.DM_ID:
                        attribValue << object.getRepeatingId(attribName, j).id
                        break
                    case IDfAttr.DM_INTEGER:
                        attribValue << object.getRepeatingInt(attribName, j)
                        break
                    case IDfAttr.DM_STRING:
                        attribValue << object.getRepeatingString(attribName, j)
                        break
                    case IDfAttr.DM_TIME:
                        attribValue << object.getRepeatingTime(attribName, j).date
                        break
	            }
            }
        }

        attribValue
    }

    /**
     * Writes multiple attribute values to an IDfTypedObject (e.g.
     * IDfPersistentObject, etc). The named parameters are:
     *
     * <ul>
     * <li>object - the typed object</li>
     * <li>attribs - a list of map objects that contain attrib info
     *   <ul>
     *   <li>attribName - the attribute name</li>
     *   <li>attribValue - the value to write</li>
     *   <li>attribType - the attribute type (optional)</li>
     *   <li>repeating - whether the attribute is a repeating value (optional)</li>
     *   </ul>
     * </li>
     * </ul>
     *
     * @param params The named parameters. See description for more info.
     * @throws DfException
     */
    def writeAttribs(Map params) {
        def object = params.object
        def attribs = params.attribs

        for(attrib in attribs) {
            writeAttrib(attrib + [object: object])
        }
    }
    
    /**
     * Writes an attribute value to an IDfTypedObject (e.g. IDfPersistentObject, etc).
     * The named parameters are:
     *
     * <ul>
     * <li>object - the typed object</li>
     * <li>attribName - the attribute name</li>
     * <li>attribValue - the value to write</li>
     * <li>attribType - the attribute type (optional)</li>
     * <li>repeating - whether the attribute is a repeating value (optional)</li>
     * </ul>
     *
     * @param params The named parameters. See description for more info.
     * @throws DfException
     */
    def writeAttrib(Map params) {
        def object = params.object
        def attribName = params.attribName
        def attribValue = params.attribValue
        def attribType = params?.attribType
        def repeating = params?.repeating
        	
        def numValues = (attribValue instanceof List) ? attribValue.size() : 1

        if(!attribType) {
            attribType = object.getAttrDataType(attribName)
        }

        if(repeating == null) {
            repeating = object.isAttrRepeating(attribName)
        }
        if(!repeating)
        {
            // single attribute
            switch(attribType)
            {
                case IDfAttr.DM_BOOLEAN:
                    object.setBoolean(attribName, attribValue ? attribValue : false)
                    break
                case IDfAttr.DM_DOUBLE:
                    object.setDouble(attribName, attribValue ? attribValue : 0)
                    break
                case IDfAttr.DM_ID:
                    if(attribValue) {object.setId(attribName, new DfId(attribValue))}
                    break
                case IDfAttr.DM_INTEGER:
                    object.setInt(attribName, attribValue ? attribValue : 0)
                    break
                case IDfAttr.DM_STRING:
                    object.setString(attribName, attribValue ? attribValue : "")
                    break
                case IDfAttr.DM_TIME:
                    if(attribValue) {object.setTime(attribName, new DfTime(attribValue)) }
                    break
            }
        }
        else
        {
            // repeating attribute
            if(attribValue && attribValue instanceof List)
            {
                object.truncate(attribName, 0)
                for(i in 0..<numValues)
                {
                    switch(attribType)
                    {
                        case IDfAttr.DM_BOOLEAN:
                            object.setRepeatingBoolean(attribName, i, attribValue[i])
                            break
                        case IDfAttr.DM_DOUBLE:
                            object.setRepeatingDouble(attribName, i, attribValue[i])
                            break
                        case IDfAttr.DM_ID:
                            if(attribValue) {object.setRepeatingId(attribName, i, new DfId(attribValue[i]))}
                            break
                        case IDfAttr.DM_INTEGER:
                            object.setRepeatingInt(attribName, i, attribValue[i])
                            break
                        case IDfAttr.DM_STRING:
                            object.setRepeatingString(attribName, i, attribValue[i])
                            break
                        case IDfAttr.DM_TIME:
                            if(attribValue) {object.setRepeatingTime(attribName, i, new DfTime(attribValue[i]))}
                            break
                    }
                }
            }
        }
    }
}